package com.gitee.wsl.time.sequence.sample

import com.gitee.wsl.time.atSecond
import com.gitee.wsl.time.sequence.InstantSequence
import kotlin.time.Instant
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlin.time.Duration.Companion.minutes
import kotlin.time.ExperimentalTime

class EveryMinuteInstant(
    private val secondsOfMinute: List<Int>,
    private val timeZone: TimeZone = TimeZone.UTC,
) : InstantSequence {

    @OptIn(ExperimentalTime::class)
    override fun generateSchedule(start: Instant): Sequence<Instant> {
        return sequence {
            var nextInstant = start
            while (true) {
                nextInstant = nextInstant.getNextAvailableSecond()
                yield(nextInstant)
            }
        }
    }

    @OptIn(ExperimentalTime::class)
    private fun Instant.getNextAvailableSecond(): Instant {
        val currentInstantAsDateTime = this.toLocalDateTime(timeZone)

        val nextAvailableSecond = secondsOfMinute
            .firstOrNull { it > currentInstantAsDateTime.second }

        return if (nextAvailableSecond != null) {
            currentInstantAsDateTime
                .atSecond(nextAvailableSecond)
                .toInstant(timeZone)
        } else {
            this
                .plus(1.minutes)
                .toLocalDateTime(timeZone)
                .atSecond(secondsOfMinute.first())
                .toInstant(timeZone)
        }
    }


    public companion object {
//        public operator fun invoke(
//            vararg secondsOfMinute: Int = IntArray(0),
//            timeZone: TimeZone = TimeZone.UTC,
//        ): EveryMinuteInstant {
//            check(secondsOfMinute.isNotEmpty()) {
//                "secondsOfMinute cannot be empty"
//            }
//            check(secondsOfMinute.all { it in 0..59 }) {
//                "all secondsOfMinute must be in range [0, 59]"
//            }
//
//            return EveryMinuteInstant(secondsOfMinute.sorted(), timeZone)
//        }
    }
}

fun InstantSequence.Companion.everyMinute(
    vararg secondsOfMinute: Int = IntArray(0),
    timeZone: TimeZone = TimeZone.UTC,
): EveryMinuteInstant {
    check(secondsOfMinute.isNotEmpty()) {
        "secondsOfMinute cannot be empty"
    }
    check(secondsOfMinute.all { it in 0..59 }) {
        "all secondsOfMinute must be in range [0, 59]"
    }
    return EveryMinuteInstant(secondsOfMinute.sorted(), timeZone)
}